package ${packageName}.api;

import ${packageName}.BuildConfig;
import ${packageName}.api.service.ContentService;
import ${packageName}.api.interceptor.AuthTokenInterceptor;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.readystatesoftware.chuck.ChuckInterceptor;

import java.io.File;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import io.ganguo.library.BaseContext;
import io.ganguo.library.Config;
import io.ganguo.library.http.cookie.CookieJarImpl;
import io.ganguo.library.http.cookie.store.PersistentCookieStore;
import io.ganguo.library.http.interceptor.APILogInterceptor;
import io.ganguo.library.http.interceptor.CacheInterceptor;
import io.ganguo.library.util.AppUtils;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class ApiClient{
	enum APIServicePath{
		content("/content-service/v1/");

		public String rawValue;
		APIServicePath(String rawValue){
			this.rawValue = rawValue;
		}
	}
	
	private ContentService contentService;

    private CookieJarImpl cookieJar;

    private static ApiClient apiClient;
    public static ApiClient getInstance(){
        if(apiClient == null){
            synchronized (ApiClient.class){
                if(apiClient == null){
                    apiClient = new ApiClient();
                }
            }
        }
        return apiClient;
    }

    private ApiClient(){
        Gson gsonInstance = createGson();
        cookieJar = new CookieJarImpl(new PersistentCookieStore(BaseContext.getInstance()));

        contentService = new Retrofit.Builder()
                .baseUrl(BuildConfig.API_BASE_URL + APIServicePath.content.rawValue)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gsonInstance))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(createHttpBuilder())
                .build()
                .create(ContentService.class);
    }

    private Gson createGson(){
        return new GsonBuilder().serializeNulls().create();
    }

    private OkHttpClient createHttpBuilder(){
        OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder()
                .cookieJar(cookieJar)
                .cache(createOkhttpCache())
                .connectTimeout(30000, TimeUnit.MILLISECONDS)
                .readTimeout(30000, TimeUnit.MILLISECONDS)
                .retryOnConnectionFailure(true)
                .followRedirects(false)
                .followSslRedirects(false)
                .hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                })
                .addInterceptor(new CacheInterceptor())
                .addNetworkInterceptor(new CacheInterceptor());

        if(BuildConfig.DEV_MODE){
            okHttpClientBuilder.addInterceptor(new APILogInterceptor());
            okHttpClientBuilder.addInterceptor(new ChuckInterceptor(AppUtils.getApp()));
        }
        okHttpClientBuilder.addInterceptor(new AuthTokenInterceptor());

        return okHttpClientBuilder.build();
    }

    private Cache createOkhttpCache() {
        File cacheFile = new File(Config.getNetworkCachePath());
        return new Cache(cacheFile, (1024 * 1024 * 100));
    }

    public ContentService getContentService(){
        return contentService;
    }
}
